package math;

import static math.ExpressionBuilder.mult;
import static math.ExpressionBuilder.pow;
import static math.IntegerConstant.MINUS_ONE;


public class Ln implements ArithmeticExpression {

  private ArithmeticExpression arg;

  private Ln(ArithmeticExpression arg) {
    this.arg = arg;
  }

  public static ArithmeticExpression createLn(ArithmeticExpression arg) {
    return new Ln(arg);
  }

  @Override
  public ArithmeticExpression derivate(Variable var) {
    return mult(arg.derivate(var), pow(arg, MINUS_ONE));
  }

  @Override
  public boolean isOne() {
    return false;
  }
  
  @Override
  public int hashCode() {
    return (arg.hashCode() >>> 1 ^ 103948203);
  }

  @Override
  public boolean isZero() {
    return arg.isOne();
  }

  @Override
  public int getPriority() {
    return 2;
  }

  @Override
  public ArithmeticExpression simplify() {
    return this;
  }

  @Override
  public String toString() {
    return "ln(" + arg.toString() + ")";
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Ln) {
      Ln ln2 = (Ln) obj;
      return ln2.arg.equals(arg);
    } else
      return false;
  }

  public ArithmeticExpression getArgument() {
    return arg;
  }

  @Override
  public boolean matches(Expression expr) {
    if (expr instanceof Ln) {
      Ln eLn = (Ln) expr;
      return arg.matches(eLn.getArgument());
    } else
      return false;
  }

  @Override
  public int countMembers() {
    return 1 + arg.countMembers();
  }

  @Override
  public <R> R accept(ExpressionVisitor<R> visitor) {
    return visitor.visitLn(this);
  }
}
